import { useState, useCallback } from 'react'

export interface ValidationRule {
  /** 是否必填 */
  required?: boolean
  /** 最小长度 */
  minLength?: number
  /** 最大长度 */
  maxLength?: number
  /** 正则表达式 */
  pattern?: RegExp
  /** 自定义验证函数 */
  validator?: (value: any) => boolean | string
  /** 错误提示信息 */
  message?: string
}

export interface FieldRules {
  [fieldName: string]: ValidationRule[]
}

export interface FormErrors {
  [fieldName: string]: string
}

export interface UseFormOptions<T> {
  /** 初始值 */
  initialValues: T
  /** 验证规则 */
  rules?: FieldRules
  /** 提交时验证 */
  validateOnSubmit?: boolean
  /** 改变时验证 */
  validateOnChange?: boolean
}

/**
 * useForm Hook
 * 表单状态和验证管理
 */
export const useForm = <T extends Record<string, any>>({
  initialValues,
  rules = {},
  validateOnSubmit = true,
  validateOnChange = false,
}: UseFormOptions<T>) => {
  const [values, setValues] = useState<T>(initialValues)
  const [errors, setErrors] = useState<FormErrors>({})
  const [touched, setTouched] = useState<Record<string, boolean>>({})
  const [isSubmitting, setIsSubmitting] = useState(false)

  /**
   * 验证单个字段
   */
  const validateField = useCallback(
    (fieldName: string, value: any): string => {
      const fieldRules = rules[fieldName]
      if (!fieldRules || fieldRules.length === 0) {
        return ''
      }

      for (const rule of fieldRules) {
        // 必填验证
        if (rule.required && !value) {
          return rule.message || `${fieldName}不能为空`
        }

        // 跳过空值的其他验证
        if (!value) continue

        // 最小长度验证
        if (rule.minLength && String(value).length < rule.minLength) {
          return rule.message || `${fieldName}至少${rule.minLength}个字符`
        }

        // 最大长度验证
        if (rule.maxLength && String(value).length > rule.maxLength) {
          return rule.message || `${fieldName}最多${rule.maxLength}个字符`
        }

        // 正则验证
        if (rule.pattern && !rule.pattern.test(String(value))) {
          return rule.message || `${fieldName}格式不正确`
        }

        // 自定义验证
        if (rule.validator) {
          const result = rule.validator(value)
          if (typeof result === 'string') {
            return result
          }
          if (!result) {
            return rule.message || `${fieldName}验证失败`
          }
        }
      }

      return ''
    },
    [rules]
  )

  /**
   * 验证所有字段
   */
  const validateAll = useCallback((): boolean => {
    const newErrors: FormErrors = {}
    let isValid = true

    Object.keys(values).forEach((fieldName) => {
      const error = validateField(fieldName, values[fieldName])
      if (error) {
        newErrors[fieldName] = error
        isValid = false
      }
    })

    setErrors(newErrors)
    return isValid
  }, [values, validateField])

  /**
   * 设置字段值
   */
  const setFieldValue = useCallback(
    (fieldName: string, value: any) => {
      setValues((prev) => ({ ...prev, [fieldName]: value }))

      // 实时验证
      if (validateOnChange && touched[fieldName]) {
        const error = validateField(fieldName, value)
        setErrors((prev) => ({
          ...prev,
          [fieldName]: error,
        }))
      }
    },
    [validateOnChange, touched, validateField]
  )

  /**
   * 设置多个字段值
   */
  const setFieldsValue = useCallback((newValues: Partial<T>) => {
    setValues((prev) => ({ ...prev, ...newValues }))
  }, [])

  /**
   * 标记字段已触碰
   */
  const setFieldTouched = useCallback((fieldName: string, isTouched: boolean = true) => {
    setTouched((prev) => ({ ...prev, [fieldName]: isTouched }))
  }, [])

  /**
   * 设置字段错误
   */
  const setFieldError = useCallback((fieldName: string, error: string) => {
    setErrors((prev) => ({ ...prev, [fieldName]: error }))
  }, [])

  /**
   * 获取字段错误
   */
  const getFieldError = useCallback(
    (fieldName: string): string => {
      return errors[fieldName] || ''
    },
    [errors]
  )

  /**
   * 重置表单
   */
  const reset = useCallback(() => {
    setValues(initialValues)
    setErrors({})
    setTouched({})
    setIsSubmitting(false)
  }, [initialValues])

  /**
   * 处理提交
   */
  const handleSubmit = useCallback(
    async (onSubmit: (values: T) => void | Promise<void>) => {
      setIsSubmitting(true)

      try {
        // 验证所有字段
        if (validateOnSubmit) {
          const isValid = validateAll()
          if (!isValid) {
            setIsSubmitting(false)
            return
          }
        }

        // 执行提交
        await onSubmit(values)
      } catch (error) {
        console.error('Form submission error:', error)
      } finally {
        setIsSubmitting(false)
      }
    },
    [validateOnSubmit, validateAll, values]
  )

  return {
    // 状态
    values,
    errors,
    touched,
    isSubmitting,

    // 方法
    setFieldValue,
    setFieldsValue,
    setFieldTouched,
    setFieldError,
    getFieldError,
    validateField,
    validateAll,
    reset,
    handleSubmit,
  }
}

export default useForm

